package com.digua.base.base

import android.content.Context
import android.content.Intent
import android.graphics.Color
import android.graphics.drawable.ColorDrawable
import android.os.Bundle
import android.view.Gravity
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.Window
import android.view.WindowManager
import androidx.activity.result.ActivityResultCallback
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.app.AppCompatDialogFragment
import androidx.fragment.app.FragmentManager
import androidx.fragment.app.FragmentTransaction
import androidx.viewbinding.ViewBinding
import com.blankj.utilcode.util.ScreenUtils
import com.digua.base.listener.RegisterForActivityResultListener
import com.digua.base.util.AuthorizeUtil
import com.digua.base.util.LogUtil
import com.digua.base.util.ViewUtil
import java.lang.reflect.ParameterizedType

open class Dialog<UI : ViewBinding> : AppCompatDialogFragment(), RegisterForActivityResultListener {
    protected lateinit var ctx: Context
    protected lateinit var ui: UI
    private var childFragmentManager: FragmentManager? = null
    private var thisManager: FragmentManager? = null
    protected var isDismiss = false
    var onDismissListener: ((Any?) -> Unit)? = null
    var tag: Any? = null
    private lateinit var launcher: ActivityResultLauncher<Intent>
    private var callback: ActivityResultCallback<Intent>? = null
    var isCancel = true
    var isCanceledOnTouchOutside = true

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        dialog?.apply {
            requestWindowFeature(Window.FEATURE_NO_TITLE) // 无标题
            window?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))// 低版本android背景透明
            setCancelable(isCancel)
            setCanceledOnTouchOutside(isCanceledOnTouchOutside) //点击边际可消失
            window?.setGravity(Gravity.CENTER)//设置弹出位置
        }
        ctx = requireContext()
        launcher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { callback?.apply { onActivityResult(it.data!!) } }
        try {
            if (javaClass.genericSuperclass is ParameterizedType) {
                val type = javaClass.genericSuperclass as ParameterizedType
                val cls = type.actualTypeArguments[0] as Class<*>
                val inflate = cls.getDeclaredMethod("inflate", LayoutInflater::class.java)
                ui = inflate.invoke(null, layoutInflater) as UI
                return ui.root
            }
        } catch (e: Exception) {
            LogUtil.e("异常:", e)
        }
        return ui.root
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        initUI()
    }

    /**
     * 设置Dialog宽度
     *
     * @param percentage 宽度占比（0~1之间）
     */
    protected open fun setWinWidth(percentage: Float) {
        if (percentage < 0 || percentage > 1) return
        val winWidth: Int = ScreenUtils.getScreenWidth()
        setWinSize((winWidth * percentage).toInt(), -100)
    }

    /**
     * 设置Dialog高度
     *
     * @param percentage 高度占比（0~1之间）
     */
    protected fun setWinHeight(percentage: Float) {
        if (percentage < 0 || percentage > 1) {
            return
        }
        val winHeight: Int = ScreenUtils.getScreenHeight()
        setWinSize(-100, (winHeight * percentage).toInt())
    }

    /**
     * 设置Dialog宽度
     *
     * @param width 宽度
     */
    protected fun setWinWidth(width: Int) {
        setWinSize(width, -100)
    }

    /**
     * 设置Dialog高度
     *
     * @param height 高度
     */
    protected fun setWinHeight(height: Int) {
        setWinSize(-100, height)
    }

    /**
     * 设置Dialog宽高
     *
     * @param widthPercentage  宽度占比（0~1之间）
     * @param heightPercentage 高度占比（0~1之间）
     */
    protected fun setWinSize(widthPercentage: Float, heightPercentage: Float) {
        if (widthPercentage < 0 || widthPercentage > 1) {
            return
        }
        var winWidth: Int = ScreenUtils.getScreenWidth()
        winWidth = (winWidth * widthPercentage).toInt()
        if (heightPercentage < 0 || heightPercentage > 1) {
            return
        }
        var winHeight: Int = ScreenUtils.getScreenHeight()
        winHeight = (winHeight * heightPercentage).toInt()
        setWinSize(winWidth, winHeight)
    }

    /**
     * 设置Dialog宽高
     *
     * @param width  宽度
     * @param height 高度
     */
    protected fun setWinSize(width: Int, height: Int) {
        var width = width
        var height = height
        val matchParent = WindowManager.LayoutParams.MATCH_PARENT
        val wrapContent = WindowManager.LayoutParams.WRAP_CONTENT
        if (width <= 0 && width != matchParent && width != wrapContent) {
            width = wrapContent
        }
        if (height <= 0 && height != matchParent && height != wrapContent) {
            height = wrapContent
        }
        dialog!!.window!!.setLayout(width, height)
    }

    open fun show(manager: FragmentManager) {
        if (!AuthorizeUtil.checkDialog()) return
        this.thisManager = manager
        if (ViewUtil.isReActionByObj(javaClass.simpleName)) {
            return
        }
        if (manager.isStateSaved || manager.isDestroyed) {
            return
        }
        try {
            if (isShowing()) return
            if (!isAdded) {
                manager.beginTransaction().add(this, javaClass.simpleName).commitAllowingStateLoss()
            }
        } catch (e: Exception) {
            LogUtil.e("异常:", e)
        }
    }

    fun show(transaction: FragmentTransaction): Int {
        if (!AuthorizeUtil.checkDialog()) return -1
        if (ViewUtil.isReActionByObj(javaClass.simpleName)) {
            return -1
        }
        if (transaction.isEmpty) {
            return super.show(transaction, null)
        }
        try {
            if (!isAdded) {
                return transaction.add(this, javaClass.simpleName).commitAllowingStateLoss()
            }
        } catch (e: Exception) {
        }
        return super.show(transaction, null)
    }

    /**
     * 初始化UI
     */
    protected open fun initUI() {}

    fun isShowing(): Boolean {
        return if (dialog == null) false else dialog!!.isShowing
    }

    fun getDialogHeight(): Int {
        return requireView().measuredHeight
    }

    fun getDialogWidth(): Int {
        return requireView().measuredWidth
    }

    override fun dismiss() {
        if (isDismiss) return
        //防止 not associated with a fragment manager
        try {
            if (isShowing()) {
                super.dismiss()
                isDismiss = true
            }
        } catch (e: Exception) {
        }
        try {
            thisManager?.beginTransaction()?.remove(this)
        } catch (e: Exception) {
        }
        onDismissListener?.let { it(null) }
    }

    fun getChildManager(): FragmentManager? {
        try {
            childFragmentManager = getChildFragmentManager()
        } catch (e: Exception) {
            checkNotNull(childFragmentManager) { "Fragment $this has not been attached yet." }
        }
        return childFragmentManager
    }

    override fun onDestroy() {
        super.onDestroy()
        //此处要调用关闭容器释放资源
        dismiss()
    }

    override fun onResume() {
        super.onResume()
        isDismiss = false
    }

    fun setOnDismissListener(onDismissListener: (Any?) -> Unit): Dialog<*> {
        this.onDismissListener = onDismissListener
        return this
    }

    override fun registerForActivityResult(intent: Intent, callback: ActivityResultCallback<Intent>) {
        this.callback = callback
        launcher.launch(intent)
    }
}